require 'benchmark'
require 'proxy_pump/proxy_timeout'
require 'proxy_pump/const'
module ProxyPump
  class FreshKeeper

    extend Forwardable

    def_delegators :client, :http, :user_agents
    attr_reader :client, :options, :retry_times

    def initialize(client, options = {})
      @client      = client
      @options     = options
      @retry_times = options.fetch(:retry_times, Const::DEFAULT_RETRY_TIMES)
    end

    # Get the region info of the specified IpAddress.
    #
    # @return [PxPump::IPInfo]
    def ipinfo(ip, options = {}, &block)
      max_retry_times = options.fetch(:retry_times, retry_times)
      begin
        res = http.get(Const::IPINFO_API_URL, params: { ip: ip })
        parsed = res.parse(Const::IPINFO_MIME).deep_symbolize_keys!
        if 0 == parsed[:code]
          parsed[:data][:province] = parsed[:data].delete(:region)
          # China's inviolable territories
          if %w(香港 澳门 台湾).include? parsed[:data][:country]
            parsed[:data][:country] = "中国"
          end
          ipinfo = parsed[:data].slice(:ip, :country, :province, :city, :area, :isp)
          if block_given?
            yield ipinfo
          else
            ipinfo
          end
        end
      rescue => e
        max_retry_times -= 1
        ProxyPump.logger.debug "Fetch #{ip} imformation failed: #{max_retry_times} retry times left. (#{e.message}) (#{e.class})"
        if max_retry_times > 0
          sleep 0.1
          retry
        else
          raise e
        end
      end
    end

    # Evaluate the proxy speed.
    #
    # @return [Integer]
    def ping(host, port, options = {}, &block)
      timeout = ProxyTimeout.new options[:timeout]
      begin
        seconds = Benchmark.realtime do
          # use a timeout of 2 * #{timeout} seconds for entire 'get' call.
          http.via(host, port)
              .timeout(timeout.type, connect: timeout.connect, read: timeout.read)
              .get(Const::PING_URL)
        end
        elapsed = (seconds * 1000).to_i
        block_given? ? (yield elapsed) : elapsed
      rescue => e
        ProxyPump.logger.error "Connect to proxy #{host}:#{port} failed. (#{e.message}) (#{e.class})"
        return nil
      end
    end

  end # FreshKeeper
end # ProxyPump
